from handlers.handler_files.handler_yaml import HandlerYaml
from handlers.handler_files.handler_ini import HandlerIni
from handlers.handler_basics import object_to_str, str_to_dict
from handlers.handler_log import logger
from handlers.handler_encryption.RSA_encryption import encrypt_by_public_key
from handlers.handler_encryption.MD5_encryption import md5_encryption

class HandlerSpecialExpression(HandlerYaml):

    def __init__(self):
        self.handler_yaml = HandlerYaml()
        self.handler_ini = HandlerIni()
        self.specialExpression = {
            'parametrizes': '指的是yaml文件的参数化的一条数据',
            'config': '指的是configurations的config.ini文件，用于存放配置文件数据',
            'extracts': '指的是data的extracts.yaml文件，用于存放指定的结果数据',
            '': '不存在specialExpression字典的key，表示节点结构关系，用于获取特定节点数据'
        }

    def specific_expression_find_parse_replay(self, data: dict, parametrize_data: list | dict = None) -> dict:
        """
        发现特殊表达式 解析特殊表达式  替换特殊表达式位置的数据
        :param parametrize_data:  用例需要修改的参数化数据
        :param data: 需要替换的数据
        :return: 替换后的数据
        """
        # 将字典数据解析为json格式的str数据 方便替换
        special_data = object_to_str(data)
        # 计算有特殊数据中几个特殊表达式
        special_symbol_number = special_data.count('${')
        # 开始搜索的位置
        start_index = 0
        for b in range(special_symbol_number):
            if '${' in special_data and '}' in special_data:
                start_index = special_data.index('${', start_index)
                end_index = special_data.index('}', start_index)
                # 防止重复查找需要解析的内容
                start_index = start_index + 1
                # 获取需要解析的特殊表达式
                special_expression = special_data[start_index + 1: end_index]
                # 执行特殊表达式,获取特殊表达式执行的表达式结果
                expression_data = self.specific_expression_parse(parametrize_data, special_expression)
                # 获取特殊表达式在特殊数据中的位置
                replace_position = special_data[start_index - 1: end_index + 1]
                # 替换解析数据
                special_data = self.specific_expression_replace(replace_position, expression_data, special_data)
        # 将替换完的接口基础数据返回
        special_data = str_to_dict(special_data)
        return special_data

    def specific_expression_parse(self, parametrize_data, special_expression: str):
        """
        解析特殊表达式，返回指定数据
        :param parametrize_data: 就是参数的一条数据
        :param special_expression: 特殊表达式
        :return: 返回指定数据 或者 返回 指定节点路径
        """
        try:
            special_expression_nodes = special_expression.split('.')
            if special_expression_nodes[0] == 'parametrizes':
                #  'parametrizes': '指的是yaml文件的参数化的一条数据',
                result_data = parametrize_data[int(special_expression_nodes[1])]
                return result_data
            elif special_expression_nodes[0] == 'config':
                # 'config': 指的是configurations的config.ini文件，用于存放配置文件数据
                result_data = self.handler_ini.get_value(special_expression_nodes[1], special_expression_nodes[2])
                return result_data
            elif special_expression_nodes[0] == 'extracts':
                # 'extracts' : 指的是data的extracts.yaml文件，用于存放指定的结果数据',
                special_expression_nodes.pop(0)
                result_data = self.handler_yaml.reader_extract_yaml(tuple(special_expression_nodes))
                return result_data
            elif special_expression_nodes[0] == 'RSA':
                # 处理RSA加密数据
                return encrypt_by_public_key(special_expression_nodes[-1])
            elif special_expression_nodes[0] == 'MD5':
                # 处理MD5加密数据
                return md5_encryption(special_expression_nodes[-1])
            else:
                # 其他 节点处理不了，需要获取到结果后 去处理，只返回个路径就行了
                return str(special_expression)
        except Exception as e:
            logger.exception(f'解析特殊表达式，返回指定数据异常： {e}')

    @staticmethod
    def specific_expression_replace(replace_position, expression_data, special_data) -> str:
        """
        用于替换yaml文件中的特定数据
        :param replace_position: 正则表达式位置（这个正则是全匹配替换）
        :param expression_data: 表达式执行后的数据，这个数据不确定什么类型
        :param special_data:  被替换的内容
        :return: yaml数据字典
        """
        if_data = expression_data
        try:
            # 当解析的表达式数据不是字符串时需要转换为字符串,但是这时替换规则也需要改变
            if isinstance(if_data, dict | int | None):
                expression_data = object_to_str(expression_data)

            replace_position_number = replace_position
            # 字典 或 数字 替换规则需要多替换一对双引号才能保证替换的数据变成字典 或 数字类型
            if isinstance(if_data, dict | int):
                replace_position_number = '"' + replace_position + '"'

            # 替换
            result_data_copy = special_data.replace(replace_position_number, expression_data)

            # 没有替换成功的情况下，这是应为有时替换的数字 并不是需要替换为数字类型，而是需要替换为字符类型，这是就不需要多替换一对双引号了
            if result_data_copy == special_data:
                result_data_copy = special_data.replace(replace_position, expression_data)

            return result_data_copy
        except Exception as e:
            logger.exception(f'用于替换yaml文件中的特定数据异常：{e}数据为：{expression_data}')


